package cloud.xlh.auth.service.impl;

import cloud.xlh.auth.domin.bo.UserInfoBO;
import cloud.xlh.auth.service.TokenService;
import cloud.xlh.exceptionhandle.service.impl.BusinessExceptionEnum;
import cloud.xlh.infrastructure.cache.operate.CacheOperateService;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 *
 * @ project name : xlh_osms
 * @ Author: XuLeHuang
 * @ Date: 2023/1/15 21:06
 * @ Description:
 */
@Slf4j
@Service
public class TokenServiceImpl implements TokenService {
    @Value("${jwt.secretKey}")
    private String secretKey;
    @Resource(name = "Redis")
    private CacheOperateService redisCacheOperateService;
    @Value("${jwt.withClaim}")
    private String jwtWithClaim;

    @Override
    public String generateToken(UserInfoBO userInfoBO) {
        Algorithm algorithm = Algorithm.HMAC256(secretKey);
        String sign = JWT.create()
                .withClaim("id", userInfoBO.getId())
                .withClaim("name", userInfoBO.getName())
                .withExpiresAt(new Date((System.currentTimeMillis() + 1000 * 60 * 4)))
                .withJWTId(UUID.randomUUID().toString())
                .withIssuedAt(new Date())
                .sign(algorithm);
        return sign;
    }

    @Override
    public boolean checkToken(JSONObject jsonObject) {
        return doCheckToken(jsonObject);
    }

    private boolean doCheckToken(JSONObject jsonObject) {
        String token = (String)jsonObject.get("token");
        try {
            UserInfoBO userInfoBO = verifyUserInfo(token);
            verifyJwt(token , userInfoBO);
            return true;
        } catch (Exception e) {
            log.error("token校验失败 ， 原因->{}" , e.getMessage());
            return false;
        }
    }

    private UserInfoBO verifyUserInfo(String token) {
        Object userInfoObject = redisCacheOperateService.getIfPresent(token);
        UserInfoBO userInfoBO = (UserInfoBO) userInfoObject;
        if (userInfoBO == null) {
            throw BusinessExceptionEnum.USERINFONOTEXIST.newException();
        }
        return userInfoBO;
    }

    private void verifyJwt(String token , UserInfoBO userInfoBO) {
        Algorithm algorithm = Algorithm.HMAC256(secretKey);
        JWTVerifier verifier = JWT.require(algorithm).withClaim(jwtWithClaim, userInfoBO.getName()).build();
        verifier.verify(token);
    }
}
